練習完kotlin 協同程式 語法,那app就來試用看看吧
嫦娥跑跑 應用程式會模擬兩位參加賽跑的玩家。應用程式 UI 包含「Start」/「Pause」和「Reset」這兩個按鈕,以及兩條顯示玩家進度的進度列。玩家 1 和 2 將以不同速度「賽跑」。賽跑開始時,玩家 2 的跑步速度是玩家 1 的兩倍。
suspend fun run() {
while (currentProgress < maxProgress) {
delay(progressDelayMillis)
currentProgress += progressIncrement
}
}
使用 LaunchedEffect() 可組合函式,就能安全地從可組合函式呼叫暫停函式。
var raceInProgress by remember { mutableStateOf(false) }
if (raceInProgress) {
LaunchedEffect(playerOne, playerTwo) {
launch {playerOne.run() }
launch {playerTwo.run() }
raceInProgress = false
}
}
改用 coroutineScope
var raceInProgress by remember { mutableStateOf(false) }
if (raceInProgress) {
LaunchedEffect(playerOne, playerTwo) {
coroutineScope {
launch { playerOne.run() }
launch { playerTwo.run() }
}
raceInProgress = false
}
}
suspend fun run() {
try {
while (currentProgress < maxProgress) {
delay(progressDelayMillis)
currentProgress += progressIncrement
}
} catch (e: CancellationException) {
Log.e("RaceParticipant", "$name: ${e.message}")
throw e // Always re-throw CancellationException.
}
}
@Test
fun raceParticipant_RaceStarted_ProgressUpdated() = runTest {
val expectedProgress = 1
launch { raceParticipant.run() }
advanceTimeBy(raceParticipant.progressDelayMillis)
runCurrent()
assertEquals(expectedProgress, raceParticipant.currentProgress)
}
@Test
fun raceParticipant_RaceFinished_ProgressUpdated() = runTest {
launch { raceParticipant.run() }
advanceTimeBy(raceParticipant.maxProgress * raceParticipant.progressDelayMillis)
runCurrent()
assertEquals(100, raceParticipant.currentProgress)
}
@Test
fun raceParticipant_RacePaused_ProgressUpdated() = runTest {
val expectedProgress = 5
val racerJob = launch { raceParticipant.run() }
advanceTimeBy(expectedProgress * raceParticipant.progressDelayMillis)
runCurrent()
racerJob.cancelAndJoin()
assertEquals(expectedProgress, raceParticipant.currentProgress)
}
@Test
fun raceParticipant_RacePausedAndResumed_ProgressUpdated() = runTest {
val expectedProgress = 5
repeat(2) {
val racerJob = launch { raceParticipant.run() }
advanceTimeBy(expectedProgress * raceParticipant.progressDelayMillis)
runCurrent()
racerJob.cancelAndJoin()
}
assertEquals(expectedProgress * 2, raceParticipant.currentProgress)
}
@Test(expected = IllegalArgumentException::class)
fun raceParticipant_ProgressIncrementZero_ExceptionThrown() = runTest {
RaceParticipant(name = "Progress Test", progressIncrement = 0)
}
@Test(expected = IllegalArgumentException::class)
fun raceParticipant_MaxProgressZero_ExceptionThrown() {
RaceParticipant(name = "Progress Test", maxProgress = 0)
}